package com.supermap.gaf.storage.resources.root;

import com.alibaba.fastjson.JSON;
import com.amazonaws.services.s3.AmazonS3;
import com.supermap.gaf.common.storage.entity.MinioConfig;
import com.supermap.gaf.common.storage.service.S3ClientService;
import com.supermap.gaf.common.storage.utils.CommonStorageUtils;
import com.supermap.gaf.common.storage.web.FileStorageResource;
import com.supermap.gaf.common.storage.web.VolumeConfigResource;
import com.supermap.gaf.commontypes.MessageResult;
import com.supermap.gaf.commontypes.pagination.Page;
import com.supermap.gaf.storage.dao.SpaceMapper;
import com.supermap.gaf.storage.entity.Space;
import com.supermap.gaf.storage.entity.SpaceConfig;
import com.supermap.gaf.storage.entity.vo.SpaceConfigSelectVo;
import com.supermap.gaf.storage.entity.vo.SpaceSelectVo;
import com.supermap.gaf.storage.enums.CreatedType;
import com.supermap.gaf.storage.enums.SelectMode;
import com.supermap.gaf.storage.resources.GlobalServerConfigResource;
import com.supermap.gaf.storage.resources.StoragePermissionResource;
import com.supermap.gaf.storage.resources.TenantSpaceConfigResource;
import com.supermap.gaf.storage.service.TenantSpaceConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.supermap.gaf.storage.config.StorageCustomConfig.MOUNT_RELOAD_URLS;

@Component
@Path("/")
@Api()
public class RootResource implements InitializingBean {

    @Resource
    private S3ClientService s3ClientService;

    @Autowired
    private TenantSpaceConfigService tenantSpaceConfigService;

    @Autowired
    private VolumeConfigResource volumeConfigResource;

    @Autowired
    private SpaceMapper spaceMapper;


    private final Map<String, FileStorageResource> fileStorageResourceMap = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        for (SelectMode item : SelectMode.values()) {
            fileStorageResourceMap.put(item.getPathName(), new FileStorageResource(s3ClientService, item));
        }
    }

    @Path("/api/{selectMode}/{configName}")
    public FileStorageResource fileStorageResource(@PathParam("selectMode") String selectMode) {
        return fileStorageResourceMap.get(selectMode);
    }

    @Path("/tenant-server-configs")
    public Class<TenantSpaceConfigResource> tenantServerConfigResource() {
        return TenantSpaceConfigResource.class;
    }

    @GET
    @Path("/tenant-allocated-space")
    @Produces({MediaType.APPLICATION_JSON})
    @ApiOperation(value = "分页条件查询", notes = "分页条件查询")
    public MessageResult<Page> allocated(@BeanParam SpaceSelectVo spaceSelectVo,
                                         @DefaultValue("1") @QueryParam("pageNum") Integer pageNum,
                                         @DefaultValue("10") @QueryParam("pageSize") Integer pageSize) {
        Page<Space> page = tenantSpaceConfigService.allocated(spaceSelectVo, pageNum, pageSize);
        return MessageResult.successe(Page.class).data(page).status(200).message("查询成功").build();
    }

    @Path("/global-server-configs")
    public Class<GlobalServerConfigResource> globalServerConfigResource() {
        return GlobalServerConfigResource.class;
    }

    @Path("/permissions")
    public Class<StoragePermissionResource> storagePermissionResource() {
        return StoragePermissionResource.class;
    }

    @Path("/volume")
    public VolumeConfigResource volumeConfigResource() {
        return volumeConfigResource;
    }


    @Path("/mount-reload")
    @Produces({MediaType.APPLICATION_JSON})
    @ApiOperation(value = "重新挂载", notes = "重新挂载")
    @POST
    public MessageResult<String> mountReload() {
        int count = 0;
        String re = "应重启%s个，成功%s个";
        if(CollectionUtils.isEmpty(MOUNT_RELOAD_URLS)){
            return MessageResult.failed(String.class).message("未找到任何挂载管理服务器【GAF_STORAGE_MOUNT_MANAGER_SERVERS】").status(500).build();
        }
        List<SpaceConfig> spaceConfigs = spaceMapper.selectSpaceConfig(SpaceConfigSelectVo.builder().createdType(CreatedType.CREATED.getValue()).build());
        for(SpaceConfig item:spaceConfigs){
            String bucketName = item.getBucketName();
            int hasSubPath = bucketName.indexOf("/");
            if(hasSubPath!=-1){
                item.setBucketName(bucketName.substring(0,hasSubPath));
            }
            MinioConfig config = MinioConfig.builder().bucketName(item.getBucketName()).serviceEndpoint(item.getServiceEndpoint()).accessKey(item.getAccessKey()).secretKey(item.getSecretKey()).build();
            CommonStorageUtils.initBucket(CommonStorageUtils.createClient(config),config);
        }
        RestTemplate restTemplate = new RestTemplate();
        List<String> messages = new ArrayList<>();
        for(String url: MOUNT_RELOAD_URLS){
            try{
                restTemplate.postForEntity(url,null,String.class);
                ++count;
            }catch (Exception e){
                messages.add(e.getMessage());
            }
        }
        return MessageResult.data(String.format(re,MOUNT_RELOAD_URLS.size(),count)).message(JSON.toJSONString(messages)).build();
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @ApiOperation(value = "验证S3Config配置", notes = "验证S3Config配置")
    @Path("/validate-s3config")
    public MessageResult<Void> validateS3Config(MinioConfig minioConfig) {
        try {
            String bucketName = minioConfig.getBucketName();
            int hasSubPath = bucketName.indexOf("/");
            if(hasSubPath!=-1){
                bucketName = bucketName.substring(0,hasSubPath);
                minioConfig.setBucketName(bucketName);
            }
            AmazonS3 s3Client = CommonStorageUtils.createClient(minioConfig);
            s3Client.doesBucketExistV2(minioConfig.getBucketName());
        } catch (Exception e) {
            return MessageResult.failed(Void.class).message(e.getMessage()).build();
        }
        return MessageResult.successe(Void.class).message("验证成功").build();
    }


}
